#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#include "../Sock/errno.hpp"
#include "../Sock/Logmessage.hpp"
namespace Server
{
    using namespace std;

    static const int gnum=1024;//缓冲区大小
    class udpServer
    {
    public:
        udpServer(const uint16_t &port)
            :port_(port),sockfd_(-1)
        {}
        void initServer()
        {
            //****创建UDP网络通信端口****
            sockfd_=socket(AF_INET,SOCK_DGRAM,0);
            if(sockfd_==-1)
            {
                logMessage(FATAL,"socket err ");
                exit(SOCKET_ERR);
            }
            

            //******绑定port，ip****
            struct sockaddr_in local;
            bzero(&local,sizeof(local));//对结构体数据清0
            local.sin_family=AF_INET;
            local.sin_port=htons(port_);//端口号转网络
            local.sin_addr.s_addr=INADDR_ANY;//任意地址绑定，服务器真正写法

            int n=bind(sockfd_,(struct sockaddr*)&local,sizeof(local));
            if(n==-1)
            {
                logMessage(FATAL,"bind err...");
                exit(BIND_ERR);
            }
            logMessage(NORMAL,"bind success...");
        }

        void start()
        {
            char buffer[gnum];
            for(;;)
            {
                struct sockaddr_in peer;
                socklen_t len=sizeof(peer);
                ssize_t s= recvfrom(sockfd_,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);
                if(s>0)
                {
                    buffer[s]=0;
                    
                    string clientip=inet_ntoa(peer.sin_addr);
                    uint16_t clientport=ntohs(peer.sin_port);
                    string message=buffer;

                    cout<<clientip<<"["<<clientport<<"]#"<<message<<endl;

                    ServerIO(clientip,clientport,message);
                }
            }
        }

        void ServerIO(string clientip,uint16_t clientport,string message)
        {
            struct sockaddr_in client;
            bzero(&client,sizeof(client));
            client.sin_family=AF_INET;
            client.sin_addr.s_addr=inet_addr(clientip.c_str());
            client.sin_port=htons(clientport);

            //发送信息
            string response="Server recv your msg, Reponse to you";
            sendto(sockfd_,response.c_str(),response.size(),0,(struct sockaddr *)&client,sizeof(client));
        }
        ~udpServer(){}
    private:
        uint16_t port_;//端口号
        string ip_;//IP地址
        int sockfd_;//文件描述符
    };
}